/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

#pragma once
#include "..\OGRE1_7SDK\include\OGRE\Ogre.h"
namespace Ogitors
{
    class CameraVisualHelper;
    //! Camera editor class
    /*!  
        A camera editor class that assists in editing camera(s) on the scene
    */
    class OgitorExport CCameraEditor: public CBaseEditor
    {
        friend class CCameraEditorFactory;

    public:
        static OgitorsPropertyDefMap propertyDefs;

        /** @copydoc CBaseEditor::getFactory() */
        static CBaseEditorFactory  *getFactory();
        /** @copydoc CBaseEditor::getFactoryDynamic() */
        virtual CBaseEditorFactory *getFactoryDynamic();
        /** @copydoc CBaseEditor::attach(CBaseEditor *) */
        virtual void     attach(CBaseEditor *parent);
        /** @copydoc CBaseEditor::detach() */
        virtual void     detach();
        /** @copydoc CBaseEditor::getObjectProperties(Ogre::NameValuePairList &) */
        virtual void     getObjectProperties(Ogre::NameValuePairList &retList);
        /** @copydoc CBaseEditor::setupPropertiesWnd(bool) */
        virtual bool     setupPropertiesWnd(bool present);
        /** @copydoc CBaseEditor::load() */
        virtual bool     load();
        /** @copydoc CBaseEditor::load() */
        virtual bool     unLoad();
        /** @copydoc CBaseEditor::setSelectedImpl(bool) */
        virtual void     setSelectedImpl(bool bSelected);
        /** @copydoc CBaseEditor::showBoundingBox(bool) */
        virtual void     showBoundingBox(bool bShow);
        /** @copydoc CBaseEditor::highlightObject(bool) */
        virtual void     highlightObject(bool highlight);

        /**
        * Fetches camera handle
        * @return camera handle
        */
        inline Ogre::Camera*  getCamera() {return m_Handle;};
        /** @copydoc CBaseEditor::postSceneUpdate(Ogre::SceneManager *, Ogre::Camera *, Ogre::RenderWindow *) */
        virtual bool     postSceneUpdate(Ogre::SceneManager *SceneMngr, Ogre::Camera *Camera, Ogre::RenderWindow *RenderWindow);
        /** @copydoc CBaseEditor::getHandle() */
        inline virtual void *getHandle() {return static_cast<void*>(m_Handle);};
        /** @copydoc CBaseEditor::restore(Ogre::NameValuePairList &) */
        virtual void     restore(Ogre::NameValuePairList &retList);
        /** @copydoc CBaseEditor::handleCustomFunction(int, Ogre::String) */
        virtual bool     handleCustomFunction(int BIND_ID, Ogre::String val);
        /** @copydoc CBaseEditor::processParameters(Ogre::NameValuePairList &) */
        virtual void     processParameters(Ogre::NameValuePairList &params);

        /**
        * Sets camera yaw value
        * @param value camera yaw value
        */
        void             yaw(const Ogre::Radian &value);
        /**
        * Sets camera pitch value
        * @param value camera pitch value
        */
        void             pitch(const Ogre::Radian &value);
        /**
        * Sets camera look-at vector coordinate
        * @param value camera look-at vector coordinate
        */
        void             lookAt(Ogre::Vector3 &value);
        /**
        * Sets camera origin position
        * @param position camera origin position
        * @param display flag signifying whether or not to update camera position field in treeview
        */
        void             setPosition(const Ogre::Vector3& position, bool display);
        /**
        * Fetches camera origin position
        * @return camera origin position
        */
        Ogre::Vector3    getPosition();
        /**
        * Sets camera orientation
        * @param orientation camera orientation
        * @param display flag signifying whether or not to update camera orientation field in treeview
        */
        void             setOrientation(const Ogre::Quaternion& orientation, bool display);
        /**
        * Fetches camera orientation
        * @return camera orientation
        */
        Ogre::Quaternion getOrientation();
        /**
        * Sets camera clipping distance
        * @param value camera clipping distance
        * @param display flag signifying whether or not to update camera clipping distance field in treeview
        */
        void             setClipDistance(const Ogre::Vector2& value, bool display);
        /**
        * Fetches camera clipping distance
        * @return camera clipping distance
        */
        Ogre::Vector2    getClipDistance();
        /**
        * Sets camera tracking target name
        * @param targetname camera tracking target name
        * @param display flag signifying whether or not to update camera tracking target name field in treeview
        */
        void             setAutoTrackTarget(const Ogre::String& targetname, bool display);
        /**
        * Fetches camera tracking target name
        * @return camera tracking target name
        */
        Ogre::String     getAutoTrackTarget();
        /**
        * Sets camera Field of View (FOV) angle
        * @param value camera FOV angle
        * @param display flag signifying whether or not to update camera FOV angle field in treeview
        */
        void             setFOV(const Ogre::Real& value, bool display);
        /**
        * Fetches camera Field of View (FOV) angle
        * @return camera Field of View (FOV) angle
        */
        Ogre::Real       getFOV();
        /**
        * Sets camera polygon mode
        * @param value camera polygon mode
        * @param display flag signifying whether or not to update camera polygon mode field in treeview
        */
        void             setPolygonMode(const int& value, bool display);
        /**
        * Fetches camera polygon mode
        * @return camera polygon mode
        */
        int              getPolygonMode();

        virtual Ogre::AxisAlignedBox getAABB();
        /** @copydoc CBaseEditor::getDerivedPosition() */
        virtual Ogre::Vector3        getDerivedPosition();
        /** @copydoc CBaseEditor::setDerivedPosition(Ogre::Vector3) */
        virtual void                 setDerivedPosition(Ogre::Vector3 val);
         /** @copydoc CBaseEditor::getDerivedOrientation() */
        virtual Ogre::Quaternion     getDerivedOrientation();

    protected:

        Ogre::Camera     *m_Handle;                                 /** Camera handle */
        Ogre::Vector3     m_Position;                               /** Camera position (wrapper) */
        Ogre::Quaternion  m_Orientation;                            /** Camera orientation (wrapper) */
        Ogre::Vector2     m_ClipDistance;                           /** Camera clipping distance (wrapper) */
        Ogre::String      m_AutoTrackTarget;                        /** Camera tracking target name (wrapper) */
        Ogre::Real        m_FOV;                                    /** Camera field of view (wrapper) */
        Ogre::PolygonMode m_PolygonMode;                            /** Camera polygon mode (wrapper) */
        CBaseEditor      *m_AutoTrackTargetPtr;                     /** Camera tracking target (wrapper) */
        OgitorsScopedConnection m_AutoTrackTargetConnection[3];     /** Camera tracking target connection(s) (wrapper) */

        /**
        * Constructor
        */
        CCameraEditor();
        /**
        * Destructor
        */
        virtual      ~CCameraEditor();

        /**
        * Delegate function that is called when tracking target was destroyed
        * @param value tracking target handle
        * @todo Figure out value parameter
        */
        void OnTrackTargetDestroyed(Ogre::Any value);
        /**
        * Delegate function that is called when tracking target' position has changed
        * @param value tracking target handle
        * @todo Figure out value parameter
        */
        void OnTrackTargetPositionChange(Ogre::Any value);
        /**
        * Delegate function that is called when tracking target' name has changed
        * @param value tracking target handle
        * @todo Figure out value parameter
        */
        void OnTrackTargetNameChange(Ogre::Any value);
    };
    //! Camera set editor factory class
    /*!  
    A class that instantiates camera editor and tracks it thereafter
    */
    class OgitorExport CCameraEditorFactory: public CBaseEditorFactory
    {
    public:
        /**
        * Constructor
        */
        CCameraEditorFactory();
        /**
        * Destructor
        */
        virtual ~CCameraEditorFactory() {};
        /** @copydoc CBaseEditorFactor::Init() */
        virtual void Init();
        /** @copydoc CBaseEditorFactor::CreateObject(CBaseEditor **, Ogre::NameValuePairList &) */
        virtual CBaseEditor *CreateObject(CBaseEditor **parent, Ogre::NameValuePairList &params);
        /** @copydoc CBaseEditorFactor::GetPlaceHolderName) */
        virtual Ogre::String GetPlaceHolderName() {return "scbCamera.mesh";};
    };
}
